﻿#include "widget.h"
#include <QtMath>

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
    , VBO(QOpenGLBuffer::VertexBuffer)
    , texture(QOpenGLTexture::Target2D)
    , texture1(QOpenGLTexture::Target2D)
{
    vertices =
    {
        // 位置              // 颜色               //纹理坐标
        0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,    1.0f, 0.0f,   // 右下
        -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,    0.0f, 0.0f,   // 左下
        -0.5f,  0.5f, 0.0f,  0.0f, 1.0f, 1.0f,    0.0f, 1.0f,   // 左下
        0.5f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f,    1.0f, 1.0f,   // 右上
    };
    timer.setInterval(18);
    connect(&timer, &QTimer::timeout, this, static_cast<void (Widget::*)()>(&Widget::update));
    timer.start();
}

Widget::~Widget()
{
}

void Widget::initializeGL()
{
    initializeOpenGLFunctions();        //初始化opengl函数
    if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/triangle.vert"))     //添加并编译顶点着色器
    {
        qDebug() << "ERROR:" << shaderProgram.log(); //如果编译出错,打印报错信息
    }
    if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/triangle.frag"))   //添加并编译片段着色器
    {
        qDebug() << "ERROR:" << shaderProgram.log(); //如果编译出错,打印报错信息
    }
    if(!shaderProgram.link())                       //链接着色器
    {
        qDebug() << "ERROR:" << shaderProgram.log(); //如果链接出错,打印报错信息
    }

    QOpenGLVertexArrayObject::Binder{&VAO};

    VBO.create();       //生成VBO对象
    VBO.bind();         //将VBO绑定到当前的顶点缓冲对象（QOpenGLBuffer::VertexBuffer）中

    //将顶点数据分配到VBO中，第一个参数为数据指针，第二个参数为数据的字节长度
    VBO.allocate(vertices.data(), sizeof(float)*vertices.size());

    texture.create();
    texture.setData(QImage("../../tex/opengl.jpg").mirrored());
    texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
    texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
    texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);

    texture1.create();
    texture1.setData(QImage("../../tex/sea.jpg").mirrored());
    texture1.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
    texture1.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
    texture1.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);

    //设置顶点解析格式，并启用顶点
    shaderProgram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 8);
    shaderProgram.enableAttributeArray("aPos");
    shaderProgram.setAttributeBuffer("aColor", GL_FLOAT, sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 8);
    shaderProgram.enableAttributeArray("aColor");
    shaderProgram.setAttributeBuffer("aTexCoord", GL_FLOAT, sizeof(GLfloat) * 6, 2, sizeof(GLfloat) * 8);
    shaderProgram.enableAttributeArray("aTexCoord");
}

void Widget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);             //定义视口区域
}

void Widget::paintGL()
{
    glClearColor(0.1f, 0.5f, 0.7f, 1.0f); //设置清屏颜色
    glClear(GL_COLOR_BUFFER_BIT);       //清除颜色缓存

    shaderProgram.bind();                     //使用shaderProgram着色程序
    {

        float time = QTime::currentTime().msecsSinceStartOfDay() / 1000.0;
        QMatrix4x4 trans;
        trans.translate(0.0f, 0.5 * qAbs(qSin(time)), 0.0f);    //向y轴平移0.5*[0,1]
        trans.scale(0.5 * qAbs(qSin(time)), 0.5 * qAbs(qSin(time))); //x，y在[0,0.5]进行缩放
        trans.rotate(360 * time, 0.0f, 0.0f, -1.0f);            //旋转360*time

        shaderProgram.setUniformValue("trans", trans);

        texture.bind(0);                                    //将texture绑定到纹理单元0
        shaderProgram.setUniformValue("ourTexture", 0);     //让ourTexture从纹理单元0中获取纹理数据

        texture1.bind(1);                                    //将texture绑定到纹理单元1
        shaderProgram.setUniformValue("ourTexture1", 1);     //让ourTexture从纹理单元1中获取纹理数据

        QOpenGLVertexArrayObject::Binder{&VAO};
        glDrawArrays(GL_POLYGON, 0, 4);   //使用以0开始，长度为4的顶点数据来绘制多边形
    }
}
